package com.ruoyi.exampaper.service.impl;


import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.ExamPaperTypeEnum;
import com.ruoyi.common.utils.DateTimeUtil;
import com.ruoyi.common.utils.ExamUtil;
import com.ruoyi.common.utils.JsonUtil;
import com.ruoyi.common.utils.ModelMapperSingle;

import com.ruoyi.common.viewmodel.ExamPaperVo;
import com.ruoyi.common.viewmodel.QuestionVo;
import com.ruoyi.common.viewmodel.exam.ExamPaperEditRequestVM;
import com.ruoyi.common.viewmodel.exam.ExamPaperTitleItemVM;
import com.ruoyi.common.viewmodel.question.QuestionEditRequestVM;
import com.ruoyi.exampaper.domain.*;
import com.ruoyi.exampaper.mapper.ExamPaperMapper;
import com.ruoyi.exampaper.service.IExamPaperService;
import com.ruoyi.question.domain.Question;
import com.ruoyi.question.service.IQuestionService;
import com.ruoyi.textcontent.domain.TextContent;
import com.ruoyi.textcontent.service.ITextContentService;
import org.modelmapper.ModelMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 试卷列表Service业务层处理
 *
 * @author ruoyi
 * @date 2023-06-25
 */
@Service
public class ExamPaperServiceImpl implements IExamPaperService {
    @Resource
    private ExamPaperMapper examPaperMapper;

    protected final static ModelMapper modelMapper = ModelMapperSingle.Instance();

    @Autowired
    private IQuestionService questionService;

    @Autowired
    private ITextContentService textContentService;

    /**
     * 返回考试试卷的具体信息
     *
     * @param id 试卷列表主键
     * @return 试卷列表
     */
    @Override
    public ExamPaperVo selectExamPaperById(Long id) {
        // 得到试卷相关信息
        ExamPaper examPaper = examPaperMapper.selectExamPaperById(id);

        Long frameTextContentId = examPaper.getFrameTextContentId();
        // 得到试卷框架，具体内容（对应标题及问题ID，JSON字符串）
        TextContent textContent = textContentService.selectTextContentById(frameTextContentId);
        String content = textContent.getContent();

        // 复制试卷相关信息内容，除具体内容
        ExamPaperVo examPaperVo = new ExamPaperVo();
        BeanUtils.copyProperties(examPaper, examPaperVo);

        // 得到试卷具体框架内容信息,这里转JSON报错，无法转换，暂未解决
//        ExamPaperTitleItemObject examPaperTitleItemObject = JsonUtil.toJsonObject(content, ExamPaperTitleItemObject.class);
//        List<ExamPaperQuestionItemObject> questionItems = examPaperTitleItemObject.getQuestionItems();


        // JSON转换失败，采取截串的方式获取id,同理获得题目排序字符串
        //ID字符串
        String idStr = "\"id\":";
        List<String> idSubString = idGetSubString(content, idStr);
        // id集合
        ArrayList<Long> questionIds = new ArrayList<Long>();
        for (String item : idSubString) {
            Long longIds = Long.valueOf(item);
            questionIds.add(longIds);
        }

        // 排序字符串
        String orderStr = "\"itemOrder\":";
        List<String> orderSubString = idGetSubString(content, orderStr);
        // id集合
        ArrayList<Long> orderIds = new ArrayList<Long>();
        for (String item : orderSubString) {
            Long longIds = Long.valueOf(item);
            orderIds.add(longIds);
        }

        // name字符串
        String nameStr = "\"name\":";
        // name集合
        List<String> names = nameGetSubString(content, nameStr);

        //根据框架内容信息中的内容，查到具体对应的题目ID，进行返回题目列表数据
        List<Question> questions = questionService.selectQuestionByIds(questionIds);

        List<QuestionVo> questionVos = new ArrayList<QuestionVo>();

        // 将题目数据复制到准备设置到页面的数据中
        List<Long> textContentIds = questions.stream().map(item -> {
            // 遍历得到contentid集合
            Long textContentId = item.getTextContentId();
            QuestionVo questionVo = new QuestionVo();
            BeanUtils.copyProperties(item, questionVo);
            questionVos.add(questionVo);

            return textContentId;
        }).collect(Collectors.toList());

        List<TextContent> textContents = textContentService.selectTextContentByIds(textContentIds);

        // 将textContent收集为map对象，便于下方题目对应数据处理
        Map<Long, String> collect = textContents.stream().collect(Collectors.toMap(TextContent::getId, TextContent::getContent, (key1, key2) -> key2));


        ExamPapaerObject examPapaerObject = new ExamPapaerObject();
        List<ExamPaperQuestionObject> examPaperQuestionObjects = new ArrayList<ExamPaperQuestionObject>();

        // 得到对应的题目具体信息数据
        for (int i = 0; i < questionIds.size(); i++) {
            examPapaerObject.setName(names.get(i));
            // 设置具体题目信息
            ExamPaperQuestionObject examPaperQuestionObject = new ExamPaperQuestionObject();
            examPaperQuestionObject.setId(questionIds.get(i));
            examPaperQuestionObject.setItemOrder(orderIds.get(i));
            String questionTextContent = collect.get(questionIds.get(i));
            examPaperQuestionObject.setQuestionContenxt(questionTextContent);

            examPaperQuestionObjects.add(examPaperQuestionObject);
        }
        examPapaerObject.setQuestionItems(examPaperQuestionObjects);

        String questionJson = JsonUtil.toJsonStr(examPapaerObject);

//        // 将题目具体信息设置到返回页面的vo列表中
//        for (int i = 0; i < questions.size(); i++) {
//            TextContent textContentforVo = textContents.get(i);
//            String textContentforVoContent = textContentforVo.getContent();
//            QuestionVo questionVo = questionVos.get(i);
//            questionVo.setContent(textContentforVoContent);
//        }
//
        examPaperVo.setFrameTextContent(questionJson);


        return examPaperVo;
    }

    /**
     *
     * @param str 原字符串（待截取原串）
     * @param posStr 指定字符串
     * @return 截取截取指定字符串之后的数据
     */
    private List<String> idGetSubString(String str, String posStr){
        Integer num = str.indexOf(posStr);
        ArrayList<String> strs = new ArrayList<>();
        while (num >=0) {
//            System.out.println(num);
            String substring = str.substring(num + posStr.length(), num + posStr.length() + 1);
            strs.add(substring);
            num = str.indexOf(posStr,num+1);
        }

        return strs;
    }
    private List<String> nameGetSubString(String str, String posStr){
        Integer num = str.indexOf(posStr);
        ArrayList<String> strs = new ArrayList<>();
        while (num >=0) {
            // 原字符串后的第一个字符
            int length = num + posStr.length();
            // 截串后第一次出现逗号的索引
            int comma = str.substring(num + posStr.length()).indexOf(",");
            String substring = str.substring(length, comma + length);
            strs.add(substring.replaceAll("\"", ""));
            num = str.indexOf(posStr,num+1);
        }

        return strs;
    }


    /**
     * 查询试卷列表列表
     *
     * @param examPaper 试卷列表
     * @return 试卷列表
     */
    @Override
    public List<ExamPaper> selectExamPaperList(ExamPaper examPaper) {
        return examPaperMapper.selectExamPaperList(examPaper);
    }

    /**
     * 新增试卷列表
     *
     * @param examPaperEditRequestVM 试卷列表
     * @return 结果
     */
    @Override
    public int insertExamPaper(ExamPaperEditRequestVM examPaperEditRequestVM) {

        List<ExamPaperTitleItemVM> titleItemsVM = examPaperEditRequestVM.getTitleItems();
        List<ExamPaperTitleItemObject> frameTextContentList = frameTextContentFromVM(titleItemsVM);
        String frameTextContentStr = JsonUtil.toJsonStr(frameTextContentList);

        ExamPaper examPaper = modelMapper.map(examPaperEditRequestVM, ExamPaper.class);

        // 添加试卷框架数据
        TextContent frameTextContent = new TextContent();
        frameTextContent.setContent(frameTextContentStr);
        textContentService.insertTextContent(frameTextContent);

        examPaper.setFrameTextContentId(frameTextContent.getId());

        examPaperFromVM(examPaperEditRequestVM, examPaper, titleItemsVM);

        return examPaperMapper.insertExamPaper(examPaper);
    }

    /**
     * 修改试卷列表
     *
     * @param examPaperEditRequestVM 试卷列表数据
     * @return 结果
     */
    @Override
    public int updateExamPaper(ExamPaperEditRequestVM examPaperEditRequestVM) {

        List<ExamPaperTitleItemVM> titleItemsVM = examPaperEditRequestVM.getTitleItems();
        List<ExamPaperTitleItemObject> frameTextContentList = frameTextContentFromVM(titleItemsVM);
        // 试卷框架数据转JSON
        String frameTextContentStr = JsonUtil.toJsonStr(frameTextContentList);

        // 更新试卷框架数据
        ExamPaper examPaper = examPaperMapper.selectExamPaperById(examPaperEditRequestVM.getId());
        TextContent frameTextContent = textContentService.selectTextContentById(examPaper.getFrameTextContentId());
        frameTextContent.setContent(frameTextContentStr);
        textContentService.updateTextContent(frameTextContent);

        modelMapper.map(examPaperEditRequestVM, examPaper);
        examPaperFromVM(examPaperEditRequestVM, examPaper, titleItemsVM);

        return examPaperMapper.updateExamPaper(examPaper);
    }

    /**
     * 批量删除试卷列表
     *
     * @param ids 需要删除的试卷列表主键
     * @return 结果
     */
    @Override
    public int deleteExamPaperByIds(String ids) {
        return examPaperMapper.deleteExamPaperByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除试卷列表信息
     *
     * @param id 试卷列表主键
     * @return 结果
     */
    @Override
    public int deleteExamPaperById(Long id) {
        return examPaperMapper.deleteExamPaperById(id);
    }

    @Override
    public ExamPaperEditRequestVM examPaperToVM(Long id) {
        ExamPaper examPaper = examPaperMapper.selectExamPaperById(id);
        ExamPaperEditRequestVM vm = modelMapper.map(examPaper, ExamPaperEditRequestVM.class);

        TextContent frameTextContent = textContentService.selectTextContentById(examPaper.getFrameTextContentId());
        List<ExamPaperTitleItemObject> examPaperTitleItemObjects = JsonUtil.toJsonListObject(frameTextContent.getContent(), ExamPaperTitleItemObject.class);
        List<Long> questionIds = examPaperTitleItemObjects.stream()
                .flatMap(t -> t.getQuestionItems().stream()
                        .map(q -> q.getId().longValue()))
                .collect(Collectors.toList());


        List<Question> questions = questionService.selectQuestionByIds(questionIds);
        List<ExamPaperTitleItemVM> examPaperTitleItemVMS = examPaperTitleItemObjects.stream().map(t -> {
            ExamPaperTitleItemVM tTitleVM = modelMapper.map(t, ExamPaperTitleItemVM.class);
            List<QuestionEditRequestVM> questionItemsVM = t.getQuestionItems().stream().map(i -> {
                Question question = questions.stream().filter(q -> q.getId().equals(i.getId())).findFirst().get();
                QuestionEditRequestVM questionEditRequestVM = questionService.getQuestionEditRequestVM(question);
                questionEditRequestVM.setItemOrder(i.getItemOrder());
                return questionEditRequestVM;
            }).collect(Collectors.toList());
            tTitleVM.setQuestionItems(questionItemsVM);
            return tTitleVM;
        }).collect(Collectors.toList());
        vm.setTitleItems(examPaperTitleItemVMS);
        vm.setScore(Long.valueOf(ExamUtil.scoreToVM(Math.toIntExact(examPaper.getScore()))));
        if (ExamPaperTypeEnum.TimeLimit == ExamPaperTypeEnum.fromCode(examPaper.getPaperType().intValue())) {
            List<String> limitDateTime = Arrays.asList(DateTimeUtil.dateFormat(examPaper.getLimitStartTime()), DateTimeUtil.dateFormat(examPaper.getLimitEndTime()));
            vm.setLimitDateTime(limitDateTime);
        }
        return vm;
    }


    private void examPaperFromVM(ExamPaperEditRequestVM examPaperEditRequestVM, ExamPaper examPaper, List<ExamPaperTitleItemVM> titleItemsVM) {


        Integer questionCount = titleItemsVM.stream()
                .mapToInt(t -> t.getQuestionItems().size()).sum();
        Integer score = titleItemsVM.stream().
                flatMapToInt(t -> t.getQuestionItems().stream()
                        .mapToInt(q -> ExamUtil.scoreFromVM(String.valueOf(q.getScore())))
                ).sum();
        examPaper.setQuestionCount(questionCount.longValue());
        examPaper.setScore(score.longValue());
        List<String> dateTimes = examPaperEditRequestVM.getLimitDateTime();
        if (ExamPaperTypeEnum.TimeLimit == ExamPaperTypeEnum.fromCode(Math.toIntExact(examPaper.getPaperType()))) {
            examPaper.setLimitStartTime(DateTimeUtil.parse(dateTimes.get(0), DateTimeUtil.STANDER_FORMAT));
            examPaper.setLimitEndTime(DateTimeUtil.parse(dateTimes.get(1), DateTimeUtil.STANDER_FORMAT));
        }
    }

    private List<ExamPaperTitleItemObject> frameTextContentFromVM(List<ExamPaperTitleItemVM> titleItems) {
        AtomicInteger index = new AtomicInteger(1);
        return titleItems.stream().map(t -> {
            ExamPaperTitleItemObject titleItem = modelMapper.map(t, ExamPaperTitleItemObject.class);
            List<ExamPaperQuestionItemObject> questionItems = t.getQuestionItems().stream()
                    .map(q -> {
                        ExamPaperQuestionItemObject examPaperQuestionItemObject = modelMapper.map(q, ExamPaperQuestionItemObject.class);
                        examPaperQuestionItemObject.setItemOrder(index.getAndIncrement());
                        return examPaperQuestionItemObject;
                    })
                    .collect(Collectors.toList());
//            titleItem.setQuestionItems(questionItems);
            return titleItem;
        }).collect(Collectors.toList());
    }
}
